﻿// Copyright (c) Inossem. All rights reserved.
// Licensed under the LGPL-3.0 license. See LICENSE file in the project root for full license information.
using DWF.Studio.RemoteCtrls.Models;
using DWF.Studio.Share.Log;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Xml.Linq;

namespace DWF.Studio.RemoteCtrls.Custom
{
    static class WPFExtensionMethods
    {
        #region 全局搜索
        public static IEnumerable<SearchActivityModel> SearchActivityByDisplayName(string searchtxt, string fullname, string fileDisplayName)
        {
            List<SearchActivityModel> searchList = new List<SearchActivityModel>();
            try
            {
                XDocument xDocument = XDocument.Load(fullname);
                IEnumerable<XElement> xElement = xDocument.Descendants();
                foreach (XElement node in xElement)
                {
                    SearchActivityModel resultModel = GetResultModels(node, searchtxt, fullname, fileDisplayName);
                    if (resultModel != null)
                    {
                        if (resultModel.xElementType == XElementType.Activity || resultModel.xElementType == XElementType.Parameter)
                        {
                            searchList.Add(resultModel);
                        }
                        else if (resultModel.xElementType == XElementType.Variable)//变量需要用父类的ID来找
                        {
                            var xattribute2 = node.Parent.Parent.Attributes().FirstOrDefault((XAttribute a) => a.Name.LocalName == "WorkflowViewState.IdRef");//.Where(o=>o.Name.LocalName=="WorkflowViewState.IdRef");
                            resultModel.IdRef = ((xattribute2 != null) ? xattribute2.Value : null);
                            searchList.Add(resultModel);
                        }
                    }
                }
                return searchList;
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
                return null;
            }
        }
        private static SearchActivityModel GetResultModels(XElement xElement, string searchtxt, string fullname, string fileDisplayName)
        {
            if (xElement.Attributes().Any((XAttribute a) => a.Name.LocalName == "WorkflowViewState.IdRef"))
            {
                SearchActivityModel activity = GetActivityModels(xElement, searchtxt, fullname, fileDisplayName, XElementType.Activity);
                if (activity != null)
                {
                    return activity;
                }
            }
            if (xElement.Name.LocalName == "Property")//参数
            {
                SearchActivityModel activity = GetActivityModels(xElement, searchtxt, fullname, fileDisplayName, XElementType.Parameter);
                if (activity != null)
                {
                    return activity;
                }
            }
            if (xElement.Name.LocalName == "Variable")//变量
            {
                SearchActivityModel activity = GetActivityModels(xElement, searchtxt, fullname, fileDisplayName, XElementType.Variable);
                if (activity != null)
                {
                    return activity;
                }
            }
            return null;
        }
        private static SearchActivityModel GetActivityModels(XElement xElement, string searchtxt, string fullname, string fileDisplayName, XElementType xElementType)
        {
            XAttribute xattribute = xElement.Attribute("DisplayName");
            if (xattribute != null)
            {
                if (xattribute.Value.ToLower().Contains(searchtxt.ToLower()))
                {
                    string text = (xattribute != null) ? xattribute.Value : null;
                    string id = string.IsNullOrWhiteSpace(text) ? xElement.Name.LocalName : text;

                    SearchActivityModel searchActivityModel = new SearchActivityModel();
                    searchActivityModel.Id = id;
                    searchActivityModel.FullName = fullname;
                    searchActivityModel.FileDisplayName = fileDisplayName;
                    searchActivityModel.DisplayName = id;
                    XAttribute xattribute2 = xElement.Attributes().FirstOrDefault((XAttribute a) => a.Name.LocalName == "WorkflowViewState.IdRef");
                    searchActivityModel.IdRef = ((xattribute2 != null) ? xattribute2.Value : null);
                    searchActivityModel.xElementType = xElementType;

                    return searchActivityModel;
                }
            }
            else if (xElement.Name.LocalName == "Property" || xElement.Name.LocalName == "Variable")
            {
                XAttribute xattributeProperty = xElement.Attribute("Name");
                {
                    if (xattributeProperty != null)
                    {
                        if (xattributeProperty.Value.ToLower().Contains(searchtxt.ToLower()))
                        {
                            string text = (xattributeProperty != null) ? xattributeProperty.Value : null;

                            SearchActivityModel searchActivityModel = new SearchActivityModel();
                            searchActivityModel.Id = text;
                            searchActivityModel.FullName = fullname;
                            searchActivityModel.FileDisplayName = fileDisplayName;
                            searchActivityModel.DisplayName = text;
                            searchActivityModel.xElementType = xElementType;

                            searchActivityModel.IdRef = xElement.Name.LocalName;//参数和变量要查询父类ID 在查找时区分不同的变量

                            return searchActivityModel;
                        }
                    }
                }
            }
            return null;
        }

        #endregion
        #region 搜索节点类
        public static childItem FindVisualChild<childItem>(DependencyObject obj) where childItem : DependencyObject
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(obj, i);
                if (child != null && child is childItem)
                    return (childItem)child;
                else
                {
                    childItem childOfChild = FindVisualChild<childItem>(child);
                    if (childOfChild != null)
                        return childOfChild;
                }
            }
            return null;
        }
        #endregion
        #region 防抖  节流阀
        private static System.Timers.Timer _timerDbc;
        private static System.Timers.Timer _timerTrt;
        /// <summary>
        /// 防抖  延迟timesMs后执行。 在此期间如果再次调用，则重新计时
        /// </summary>
        /// <param name="invoker">同步对象，一般为Control控件。 如不需同步可传null</param>
        public static void Debounce(int timeMs, ISynchronizeInvoke invoker, Action action, UserControl window)
        {
            lock (window)
            {
                if (_timerDbc == null)
                {
                    _timerDbc = new System.Timers.Timer(timeMs);
                    _timerDbc.AutoReset = false;
                    _timerDbc.Elapsed += (o, e) =>
                    {
                        _timerDbc.Stop();
                        _timerDbc.Close();
                        _timerDbc = null;
                        invokeAction(action, invoker);
                    };
                }
                _timerDbc.Stop();
                _timerDbc.Start();
            }
        }
        /// <summary>
        /// 节流阀  即刻执行，执行之后，在timeMs内再次调用无效
        /// </summary>
        /// <param name="timeMs">不应期，这段时间内调用无效</param>
        /// <param name="invoker">同步对象，一般为控件。 如不需同步可传null</param>
        public static void Throttle(int timeMs, ISynchronizeInvoke invoker, Action action, UserControl window)
        {
            System.Threading.Monitor.Enter(window);
            bool needExit = true;
            try
            {
                if (_timerTrt == null)
                {
                    _timerTrt = new System.Timers.Timer(timeMs);
                    _timerTrt.AutoReset = false;
                    _timerTrt.Elapsed += (o, e) =>
                    {
                        _timerTrt.Stop();
                        _timerTrt.Close();
                        _timerTrt = null;
                    };
                    _timerTrt.Start();
                    System.Threading.Monitor.Exit(window);
                    needExit = false;
                    invokeAction(action, invoker);//这个过程不能锁
                }
            }
            finally
            {
                if (needExit)
                    System.Threading.Monitor.Exit(window);
            }
        }
        public static void invokeAction(Action action, ISynchronizeInvoke invoker)
        {
            if (invoker == null)
            {
                action();
            }
            else
            {
                if (invoker.InvokeRequired)
                {
                    invoker.Invoke(action, null);
                }
                else
                {
                    action();
                }
            }
        }
        #endregion
    }
}
